package lrz.shiftplanner.components;

import java.awt.Color;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;

import lrz.shiftplanner.application.MainWindow;
import lrz.shiftplanner.calendar.Assignment;
import lrz.shiftplanner.calendar.Day;
import lrz.shiftplanner.calendar.DayState;
import lrz.shiftplanner.calendar.DayType;
import lrz.shiftplanner.calendar.ShiftType;
import lrz.shiftplanner.staff.Person;

public class Selector extends JPanel {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1426265021388263750L;
	private static JPopupMenu popUp1 = null;
	private static JPopupMenu popUp2 = null;
	
	private JButton button;
	private JProgressBar bars[];
	private Color barColor[] = new Color[]{Colors.cMarkedBG, Colors.cMarkedBG2, Colors.cMarkedBG};
	private JPanel panel1;
	private JPanel panel2;
	private Day day;
	private Border border;
	private boolean showHint;
	private boolean assigned;
	private Assignment assignment;
	
	
	public String getText() {
		String result = assignment.getShiftsString(assignment.getShifts(person, day));
		// hack
		if (result.length()>2)
			return "W13";
		else
			return result;
	}
	

	
	public LinkedList<GuiListener> guiListeners = new LinkedList<GuiListener>();
	//public MainWindow mainWindow;

	private final Person person;
	
	private static void initPopUp() {
		popUp1 = new JPopupMenu();
		popUp2 = new JPopupMenu();
		
		List<JMenuItem> items = new ArrayList<JMenuItem>();
		items.add(new JMenuItem(" "));
		items.add(new JMenuItem("B"));
		items.add(new JMenuItem(" "));
		items.add(new JMenuItem("B"));
		items.add(new JMenuItem("W13"));
		
		
		
		List<String> ids = DayType.getShiftTypeDescriptors(DayType.Regular);
		popUp1.add(items.get(0));
		for (int i=0;i<ids.size();i++) {
			JMenuItem item = new JMenuItem(ids.get(i));
			item.setBackground(Colors.getShiftColor(ShiftType.valueOf(ids.get(i))));
			popUp1.add(item);
			items.add(item);
		}
		
		popUp1.add(items.get(1));
		ids = DayType.getShiftTypeDescriptors(DayType.Holiday);
		popUp2.add(items.get(2));
		for (int i=0;i<ids.size();i++) {
			JMenuItem item = new JMenuItem(ids.get(i));
			item.setBackground(Colors.getShiftColor(ShiftType.valueOf(ids.get(i))));
			popUp2.add(item);
			items.add(item);
		}
		popUp2.add(items.get(4));
		items.get(4).setBackground(Colors.getShiftColor(ShiftType.W3));
		
		popUp2.add(items.get(3));

		
		
		ActionListener al = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				JMenuItem item = (JMenuItem) e.getSource();
				Selector b = (Selector) ((JPopupMenu) (item).getParent())
						.getInvoker();
				b.selectShift(item.getText());
			}
		};

		for (JMenuItem m : items)
			m.addActionListener(al);
		
		for (JMenuItem item : items) {
			item.setFont(new Font("Arial", Font.PLAIN, 18));
		}

	}


	
	
	private void switchLayer() {
		if (showHint && !assigned) {
			remove(panel1);
			add(panel2, BorderLayout.CENTER);
		} else {
			remove(panel2);
			add(panel1, BorderLayout.CENTER);
		}
		validate();
	}
	
	private void createBars() {
		if (bars!=null)
			for (int i=0;i<bars.length;i++) {
				if (bars[i]!=null)
					panel2.remove(bars[i]);
				bars[i] = null;
			}
		bars = new JProgressBar[day.getNumberOfShiftTypes()];
		List<String> ids = day.getShiftTypeDescriptors();
		panel2.setLayout(new GridLayout(ids.size(), 0, 1, 1));
		
		

		for (int i=0;i<ids.size();i++) {
			UIManager.put("ProgressBar.foreground", barColor[i]);
			bars[i] = new JProgressBar(SwingConstants.HORIZONTAL, 0, 
					DayType.getShiftTypeCapacity(day.getDayType(), ShiftType.valueOf(ids.get(i))));
			bars[i].setString(ids.get(i));
			//bars[i].setStringPainted(true);
			bars[i].setValue(1);
			panel2.add(bars[i]);
		}
		
	}

	public Selector(Person person, Day day, Assignment s) {
		
		this.person = person;
		this.day = day;
		showHint = false;
		assigned = false;
		assignment = s;

		setLayout(new BorderLayout());
		setBorder(null);
		
		
		panel1 = new JPanel();
		panel2 = new JPanel();

		button = new JButton("");
		panel1.setLayout(new BorderLayout());
		panel1.add(button, BorderLayout.CENTER);
		
//		panel2.setLayout(new GridLayout(3,1));
//		for (int i=0;i<3;i++) {
//			bars[i] = new JProgressBar(SwingConstants.HORIZONTAL, 0, 2);
//			panel2.add(bars[i]);
//		}
		
		createBars();
		

		
		
		if (popUp1 == null)
			initPopUp();

		button.setPreferredSize(new Dimension(10, 10));
		button.setMargin(new Insets(0, 0, 0, 0));
		button.setFont(AdaptFontFactory.registerFont(this, AdaptFontFactory.SELECTOR));
		// save original border
		border = button.getBorder();
		refreshAppearance();
		ActionListener al = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				showPopUp(10, 10);
			}
		};
		
		button.addActionListener(al);
		
		MouseListener ml = new MouseAdapter() {
			public void mouseClicked(MouseEvent m) {
				showPopUp(10, 10);
			}
		};
		
		panel2.addMouseListener(ml);
		
		
		
		switchLayer();
	}
	
//	public Selector(Person p, Day day, ShiftType loadType) {
//		this(p, day);
//		//this.loadType = loadType;
//	}

	public Day getDay() {
		return day;
	}

	public Person getPerson() {
		return person;
	}
	
	public String getHTMLText() {
		String result = assignment.getShiftsString(assignment.getShifts(person, day));
		if (result.length()<3)
			return result;
		else
			// Hack
			return "<html>W1<br>W3";
	}


	public boolean isShowHint() {
		return showHint;
	}
	
	public boolean isAssigned() {
		return assigned;
	}

	public void selectShift(String popUpMenuText) {
		
		if (popUpMenuText.equals(" ")) {
			assignment.removeAll(person, day);
			assigned = false;
		} else {
			assignment.removeAll(person, day);
			assigned = false;

			if (popUpMenuText.length() == 1 || popUpMenuText.length() == 2) {
				assignment.assign(person, day, ShiftType.valueOf(popUpMenuText));
				assigned = true;
			} else {
				assignment.assign(person, day, ShiftType.W1);
				assignment.assign(person, day, ShiftType.W3);
				assigned = true;
			}
		}
		
		for (GuiListener l : guiListeners)
			l.actionPerformed(GuiEvent.SelectorChanged, this);
		refreshAppearance();
		switchLayer();
	}

	public void setHint(boolean showHint) {
		if (this.showHint != showHint) {
			this.showHint = showHint;
			refreshAppearance();
		}
		switchLayer();
	}
	
	

	public void refreshAppearance() {
		// set background
		if (!assigned) {
			button.setForeground(Colors.cHintF);
			button.setBorder(border);
			if (!MainWindow.updateMode)
				button.setFont(AdaptFontFactory.registerFont(this,
						AdaptFontFactory.SELECTORSMALL));
//			else if (loadType!=type)
//				setBorder(new LineBorder(Colors.cUpdatedBG, MainWindow.updateMode ? 3 : 1));
			
			if (day.getState()==DayState.Complete)
				button.setBackground(Colors.cCorrectBG);
			else if (day.getState()==DayState.MissingStandby)
				button.setBackground(Colors.cStandbyBG);
			else if (day.getState()==DayState.Invalid)
				button.setBackground(Colors.cInvalidBG);
			else
				button.setBackground(day.getDayType()==DayType.Regular ? 
						Colors.cWorkingDayBG : Colors.cHolidayBG);
		} else {
			button.setForeground(Colors.cSolidF);
			button.setFont(AdaptFontFactory.registerFont(this,
					AdaptFontFactory.SELECTOR));
			button.setContentAreaFilled(true);
			button.setBackground(null);
			// set border
//			if (MainWindow.updateMode)
//				setBorder(new LineBorder(loadType!=type ? Colors.cUpdatedBG : Color.LIGHT_GRAY, 3));
//			else
			button.setBorder(new LineBorder(day.getState()==DayState.Complete ? Colors.cCorrectB
					: day.getState()==DayState.MissingStandby ? Colors.cStandbyB : Colors.cInvalidB));
		}
		
		// set text
		if (!assigned) {
//			if (loadType!=ShiftType.Deactivated)
//				setText(loadType.toString());
//			else 
			button.setText("");
		} else {
			button.setText(getHTMLText());
			switchLayer();
		}
		for (int i=0;i<bars.length;i++) {
			bars[i].setValue(day.getValidShiftTypeCountRemaining(i));
		}
	}

	public void showPopUp(int x, int y) {
		if (day.getDayType()!=DayType.Regular)
			popUp2.show(this, x, y);
		else
			popUp1.show(this, x, y);
	}
	
	public void refreshType() {
		createBars();
		validate();
	}

	public void setLoadType(ShiftType t) {
		//loadType = t;
		//System.out.println(t.toString());
	}

}